--[[ New Pause Menu ]] --
-- by EeveeEuphoria

-- CREATED FOR INTERNAL USE IN THIS EPISODE!

--[[ TODO:
    - If "N/A" is reported in Star Coins menu, do one of the following;
        - If the level's star coin counter is above 0, then fill out the spaces w/ the amount of star coins.
]]

local newPauseMenu = {}

function newPauseMenu.onInitAPI()
	registerEvent(newPauseMenu, "onTick")
	registerEvent(newPauseMenu, "onStart")
	registerEvent(newPauseMenu, "onDraw")
	registerEvent(newPauseMenu, "onPause")
	registerEvent(newPauseMenu, "onInputUpdate")
end

-- player.rawKeys.pause

local restartcountdown = 0

local pauseTime = false
local position = 1
local cursorposX = 245
local cursorposY = 0
local fakecursorposX = cursorposX
local fakecursorposY = cursorposY
local spacing = 40
local yoffset = -14
local xoffset = 0
local opacity = 0

local menuOptions = {}

local playerincontrol = nil
local cooldown = 0

local PichuTime = false
local shinypichu = false

local pauseGFX = Graphics.loadImage(Misc.resolveFile("GFX/pause.png"))
local pauseGFXYOffset = 0
local pauseGFXXOffset = 0
local cursorGFX = Graphics.sprites.hardcoded["34-0"].img
local HardModeGFX = Graphics.loadImage(Misc.resolveFile("GFX/hard mode incomplete.png"))
local HardModeGFX2 = Graphics.loadImage(Misc.resolveFile("GFX/hard mode.png"))

local function booleantostring(bln)
    if type(bln) == "boolean" then
        if bln then
            return "On"
        else
            return "Off"
        end
    else
        return bln
    end
end

local function unpause(plyr)
    Misc.unpause()
    pauseTime = false
    plyr:mem(0x11E,FIELD_BOOL,false)
end

local function save()
    Misc.saveGame()
end

local function exit()
    Misc.exitGame()
end

local function saveexit()
    Misc.saveGame()
    Misc.exitGame()
end

local function exittohub(plyr)
    if plyr:isOnGround() then
        local WarpTime = mem(0x00B2C6D8,FIELD_WORD) or 0
        Level.load("Mario Castle.lvlx", nil, WarpTime)
        unpause(plyr)
    else
        SFX.play(39)
        return
    end
end

local function restart(plyr)
    unpause(plyr)
    if GameData.PlayerWarp > 0 then
        mem(0x00B2C6DA, FIELD_WORD, GameData.PlayerWarp)
    else
        mem(0x00B2C6DA, FIELD_WORD, -1)
    end
    mem(0x00B25720, FIELD_STRING, Level.filename());
    mem(0x00B250B4, FIELD_WORD, 0);
    mem(0x00B25134, FIELD_WORD, 0);
    mem(0x00B2C89C, FIELD_WORD, 0);
    mem(0x00B2C620, FIELD_WORD, 0);
    mem(0x00B2C5B4, FIELD_WORD, -1);
end

local startrestartcountdown = false

local function restartwcoins(plyr)
    local Coinz = 10
    if globalsave.HardMode then
        Coinz = 20
    end
    if myCurrency._value > Coinz then
        changemoney(-Coinz)
        Audio.playSFX(Misc.resolveFile("coinFX/coin" .. RNG.randomInt(1, 3) .. ".ogg"))
        startrestartcountdown = plyr
    else
        SFX.play(39)
    end
end

local function addOption(tbl)
    table.insert(menuOptions, tbl)
end

function newPauseMenu.onPause(eventToken, pausingPlayer)
    eventToken.cancelled = true
end

local logoGFX

-- globalsave.RestartOnDeath

local function ChangeOption(option)
    globalsave[option] = not globalsave[option]
end

local function ChangeNumOption(option, min, max)
    globalsave[option] = globalsave[option] + 1
    if globalsave[option] > max then
        globalsave[option] = min
    end
end

local function OptionsMenu()
    menuOptions = {}
    addOption{name = "Restart on Death", action = ChangeOption, changesetting = "RestartOnDeath", sound = 59}
    if globalsave.WaterBoots then
        addOption{name = "Liquid Boots", action = ChangeOption, changesetting = "WaterShoesOn", playersave = true, sound = 59}
        addOption{name = "Liquid Boots HUD", action = ChangeNumOption, changesetting = "WBHUD", number = true, from = 1, to = 2, sound = 59}
    end
    if globalsave.HardModePurchase and Level.name() == "Mario Castle" then
        addOption{name = "Hard Mode", action = ChangeOption, changesetting = "HardMode", sound = 59}
    end
    addOption{name = "Return to Menu", action = RestoreMenu, sound = 59}
    spacing = 24
    yoffset = -22
    xoffset = -30
    position = 1
end

local function Nothing()
    -- you get nothing! you lose! good day sir!
end

local page = 1
local itemsperpage = 5
local maxpages = 2

local function ChangePage(numb, refresher)
    page = page + numb
    if page > maxpages then
        page = 1
    elseif page < 1 then
        page = maxpages
    end
    refresher(true)
end


--IDEA FOR INDIVIDUAL LEVEL MENUS: Display only the ones that haven't had any stars collected in them.
-- Also display the world number in front!

-- getCollectedStarCount(Level.filename())

local pagessys = false
local pagesaction

local function LevelsMenu(stopchange)
    pauseGFX = Graphics.loadImage(Misc.resolveFile("GFX/pause 2.png"))
    pauseGFXYOffset = -96
    pauseGFXXOffset = -20
    menuOptions = {}
    pagessys = true
    pagesaction = LevelsMenu
    for index, value in ipairs(LevelsTable) do
        if (index) <= math.floor(itemsperpage)*page and (index) > math.floor(itemsperpage)*(page-1) then
            if value.level and tonumber(FileFormats.openLevelHeader(value.level).stars) and value.level ~= "Mario Castle.lvlx" then
                local stringman3 = ""
                if globalsave.HardModePurchase then
                    if globalsave.HMLevelsBeat[value.level] then
                        stringman3 = " ☠️"
                    else
                        stringman3 = " 💀"
                    end
                end
                addOption{name = value.name .. stringman3, action = Nothing, nocursor = true, font = GoodFont3}
                -- [ Star Coins ] --
                local starCoinsT = SaveData._basegame.starcoin[value.level]
                local stringman = ""
                if starCoinsT then
                    for index2, value2 in ipairs(starCoinsT) do
                        if value2 == 1 then
                            stringman = stringman .. "🌟 "
                        else
                            stringman = stringman .. "⭐ "
                        end
                    end
                end
                if stringman == "" then
                    if SearchLevelName(value.level).starcoins then
                        for i=SearchLevelName(value.level).starcoins, 1, -1 do
                            stringman = stringman .. "⭐ "
                        end
                    else
                        stringman = "N/A"
                    end
                end
                local collectStarCount = getCollectedStarCount(value.level)
                local totalStarCount = FileFormats.openLevelHeader(value.level).stars
                local stringman2 = ""
                if totalStarCount then
                    for i=collectStarCount, 1, -1 do
                        stringman2 = stringman2 .. "🌟 "
                    end
                    for i=totalStarCount-collectStarCount, 1, -1 do
                        stringman2 = stringman2 .. "⭐ "
                    end
                end
                --stringman2 = totalStarCount
                if stringman2 == "" then
                    stringman2 = "N/A"
                end
                --addOption{name = "   " .. collectStarCount .. "/" .. totalStarCount, action = Nothing, nocursor = true, font = GoodFont2}
                addOption{name = "   " .. stringman2, action = Nothing, nocursor = true, font = GoodFont3}
                addOption{name = "   " .. stringman, action = Nothing, nocursor = true, font = GoodFont2}
            end
        end
    end

    maxpages = math.ceil((table.getn(LevelsTable)-1) / itemsperpage)

    addOption{name = "Page: " .. page .. "/" .. maxpages, action = Nothing, argument = 1, sound = 59, nocursor = true}
    addOption{name = "Return to Progress", action = ProgressMenu, sound = 59, dontmove = true}

    spacing = 24
    xoffset = -30 + pauseGFXXOffset
    yoffset = -27 + pauseGFXYOffset

    if not stopchange then
        position = 1
    elseif position > table.getn(menuOptions) then
        position = table.getn(menuOptions)
    end
end

local function Upgrades(stopchange)
    menuOptions = {}
    pagessys = true
    pagesaction = Upgrades

    for index, value in ipairs(UpgradesTable) do
        local string = 0
        if globalsave[value.globalsave] then
            string = value.name
        else
            string = "???"
        end
        addOption{name =  string, action = Nothing, nocursor = true, color = Color.fromHexRGB(0xAFAFAF)}
    end

    maxpages = math.ceil(table.getn(UpgradesTable) / itemsperpage)

    addOption{name = "Page: " .. page .. "/" .. maxpages, action = Nothing, argument = 1, sound = 59, nocursor = true}
    addOption{name = "Return to Progress", action = ProgressMenu, sound = 59, dontmove = true}

    spacing = 24
    yoffset = -22
    xoffset = -30
    if not stopchange then
        position = 1
    elseif position > table.getn(menuOptions) then
        position = table.getn(menuOptions)
    end
end

function ProgressMenu()
    menuOptions = {}
    pagessys = false
    pagesaction = nil
    page = 1

    if pauseGFXYOffset ~= 0 then
        pauseGFX = Graphics.loadImage(Misc.resolveFile("GFX/pause.png"))
        pauseGFXYOffset = 0
        pauseGFXXOffset = 0
    end

    local Thing = "1. Toad Town"
    if globalsave.FixElevator then
        Thing = "???"
    elseif globalsave.OpenCastle then
        Thing = "3. Hot Snow"
    elseif globalsave.SaveTheTown then
        Thing = "2. Bridge Lands"
    elseif globalsave.DefeatBirdo then
        Thing = "2. Gray Pipe?"
    end
    addOption{name = "World: " .. Thing, action = Nothing, sound = 59, nocursor = true, color = Color.fromHexRGB(0xAFAFAF)}
    addOption{name = "Stars: " .. mem(0x00B251E0, FIELD_WORD) .. "/" .. mem(0xB2C906, FIELD_WORD), action = Nothing, sound = 59, nocursor = true, color = Color.fromHexRGB(0xAFAFAF)}
    addOption{name = "Star Coins: " .. SaveData._basegame.starcoinCounter .. "/" .. TotalStarCoins, action = Nothing, sound = 59, nocursor = true, color = Color.fromHexRGB(0xAFAFAF)}
    addOption{name = "Levels", action = LevelsMenu, sound = 59}
    addOption{name = "Upgrades: " .. CollectedUpgrades() .. "/" .. table.getn(UpgradesTable), action = Upgrades, sound = 59}
    addOption{name = "Return to Menu", action = RestoreMenu, sound = 59}
    spacing = 24
    yoffset = -22
    xoffset = -30
    position = 1
end

local CHEATDETECTED = false

local function HubMenu()
    menuOptions = {}
    pagessys = false
    pagesaction = nil
    page = 1
    spacing = 30
    yoffset = -18
    xoffset = -16
    position = 1
    addOption{name = "Continue", action = unpause, playerneeded = true, sound = 30}
    addOption{name = "Progress", action = ProgressMenu, sound = 59}
    addOption{name = "Options", action = OptionsMenu, sound = 59}
    if not Defines.player_hasCheated then
        addOption{name = "Save & Continue", action = save, unpause = true, sound = "SFX/save.wav"}
        addOption{name = "Save & Exit", action = saveexit, unpause = true, sound = "SFX/save.wav"}
        yoffset = -20
    else
        addOption{name = "Exit", action = exit, unpause = true, sound = 59}
        spacing = 36
    end
end

local function RegularMenu()
    menuOptions = {}
    pagessys = false
    pagesaction = nil
    page = 1
    addOption{name = "Continue", action = unpause, playerneeded = true, sound = 30}
    addOption{name = "Options", action = OptionsMenu, sound = 59}
    local Coinz = 10
    if globalsave.HardMode then
        Coinz = 20
    end
    addOption{name = "Restart 💵x" .. Coinz, action = restartwcoins, font = GoodFont2, playerneeded = true, altname = "Restart"} 
    addOption{name = "Exit to Hub World", action = exittohub, playerneeded = true}
    spacing = 35
    yoffset = -15
    xoffset = -16
    position = 1
end

function RestoreMenu()
    if Level.name() == "Mario Castle" then
        HubMenu()
    else
        RegularMenu()
    end
end



function newPauseMenu.onStart()
    GameData.PlayerWarp = player:mem(0x15E, FIELD_WORD) or 0
    RestoreMenu()
    local WorldNumber = 0
    if SearchLevelName(Level.filename()) then
        WorldNumber = SearchLevelName(Level.filename()).world
    end
    logoGFX = Graphics.loadImage(Misc.resolveFile("GFX/unusuality logo " .. WorldNumber .. ".png"))
end

-- gplayerData[plyr.idx].WaterShoesOn

local ForceButton = false

function newPauseMenu.onInputUpdate()
    if restartcountdown > 0 then return end
    for _,plyr in ipairs(Player.get()) do
        if plyr.rawKeys.pause == KEYS_PRESSED and plyr.deathTimer == 0 and not mem(0x00B250E2, FIELD_BOOL) then
            pauseTime = not pauseTime
            page = 1
            position = 1
            cooldown = 2
            cursorposY = 220+(spacing*position)
            fakecursorposY = cursorposY
            if pauseTime then
                if Misc.isPaused() then
                    Misc.unpause()
                else
                    Misc.pause()
                end
            else
                Misc.unpause()
            end
            playerincontrol = plyr
            if RNG.randomInt(1, 69) == 42.0 or GameData.PichuTime then
                PichuTime = true
                if RNG.randomInt(1, 420) == 69 or GameData.Masuda then
                    shinypichu = true
                end
            end
            SFX.play(30)
        end
    end

    if pauseTime and playerincontrol then
        if cooldown > 0 then
            cooldown = cooldown - 1
        end
        if playerincontrol.rawKeys.down == KEYS_PRESSED and not menuOptions[position].dontmove then
            position = position + 1
            if position > table.getn(menuOptions) then
                position = 1
            end
            SFX.play(71)
        elseif playerincontrol.rawKeys.up == KEYS_PRESSED and not menuOptions[position].dontmove then
            position = position - 1
            if position < 1 then
                position = table.getn(menuOptions)
            end
            SFX.play(71)
        elseif playerincontrol.rawKeys.left == KEYS_PRESSED and pagessys then
            ChangePage(-1, pagesaction)
            SFX.play(71)
        elseif playerincontrol.rawKeys.right == KEYS_PRESSED and pagessys then
            ChangePage(1, pagesaction)
            SFX.play(71)
        elseif playerincontrol.rawKeys.run == KEYS_PRESSED then
            position = table.getn(menuOptions)
            local OptionChosen = menuOptions[position]
            if OptionChosen.name ~= "Exit" and OptionChosen.name ~= "Exit to Hub World" and OptionChosen.name ~= "Save & Exit" then
                ForceButton = true
            else
                position = 1
                ForceButton = true
            end
        elseif playerincontrol.rawKeys.pause == KEYS_PRESSED and cooldown == 0 then
            unpause(playerincontrol)
            RestoreMenu()
        elseif playerincontrol.rawKeys.jump == KEYS_PRESSED or ForceButton then -- choose option
        -- or (playerincontrol.rawKeys.pause == KEYS_PRESSED and cooldown == 0)
            local OptionChosen = menuOptions[position]
            local argument
            local arg2
            local arg3
            ForceButton = false
            if OptionChosen.playerneeded then
                argument = playerincontrol
            elseif OptionChosen.changesetting then
                argument = OptionChosen.changesetting
                if OptionChosen.playersave then
                    argument = OptionChosen.changesetting .. playerincontrol.idx
                end
                if OptionChosen.number then
                    arg2 = OptionChosen.from
                    arg3 = OptionChosen.to
                end
            elseif OptionChosen.argument then
                argument = OptionChosen.argument
                if OptionChosen.argument2 then
                    arg2 = OptionChosen.argument2
                end
            end

            OptionChosen.action(argument, arg2, arg3)

            if OptionChosen.unpause then
                unpause(playerincontrol, true)
            end
            if OptionChosen.sound then
                if tonumber(OptionChosen.sound) then
                    SFX.play(OptionChosen.sound)
                else
                    Audio.playSFX(OptionChosen.sound)
                end
            end
        end
    else
        playerincontrol = nil
    end
end

--cursorGFX = Graphics.loadImage(Misc.resolveFile("GFX/player2pause.png"))

function newPauseMenu.onTick()
    if CHEATDETECTED ~= Defines.player_hasCheated then
        CHEATDETECTED = Defines.player_hasCheated
        RestoreMenu()
    end
    if playerincontrol and Level.name() == "Mario Castle" then
        local SectionNumber = 0
        if playerincontrol.section == 2 or playerincontrol.section == 6 then
            SectionNumber = 1
        elseif playerincontrol.section == 4 or playerincontrol.section == 5 then
            SectionNumber = 2
        elseif playerincontrol.section == 7 then
            SectionNumber = 3
        elseif playerincontrol.section == 8 then
            SectionNumber = 4
        end
        logoGFX = Graphics.loadImage(Misc.resolveFile("GFX/unusuality logo " .. SectionNumber .. ".png"))
        --[[if GameData.TransFlag then
            pauseGFX = Graphics.loadImage(Misc.resolveFile("GFX/trans pause.png"))
        else
            pauseGFX = Graphics.loadImage(Misc.resolveFile("GFX/pause.png"))
        end]]
    end

    if PichuTime and not pauseTime and opacity <= 0 then
        PichuTime = false
        shinypichu = false
    end
end

local xposgoto = 12
local xpostimer = -xposgoto
local pichutimer = 0
local pichutimer2 = 0

function newPauseMenu.onDraw()
    if startrestartcountdown then
        restartcountdown = restartcountdown + 1
        if restartcountdown >= 45 then
            restart(startrestartcountdown)
        end
    end
    local OptionSelection = menuOptions[position]
    if OptionSelection.nocursor then
        position = position + 1
    end
    if pauseTime then
        if opacity < 1 then
            opacity = opacity + 0.1
        end
    else
        if opacity > 0 then
            opacity = opacity - 0.2
        end
    end

    if opacity > 0 then
        Graphics.drawImageWP(pauseGFX, 200 + pauseGFXXOffset, 152 + pauseGFXYOffset, opacity, 5)
        Graphics.drawImageWP(logoGFX, 216, 156 + pauseGFXYOffset, opacity, 5)
        for key, value in pairs(menuOptions) do
            local colortime = Color.white
            if value.color then
                colortime = value.color
            end
            if position == key and not value.nocursor then
                if playerincontrol == player2 then
                    colortime = Color.fromHexRGB(0x7FC3FF)
                else
                    colortime = Color.fromHexRGB(0xFF7F7F)
                end
            end
            -- gray out invalid options
            if (playerincontrol and not playerincontrol:isOnGround() and value.name == "Exit to Hub World") or (value.altname == "Restart" 
            and ((not globalsave.HardMode and myCurrency._value < 10) or globalsave.HardMode and myCurrency._value < 20)) then
                colortime = Color.fromHexRGB(0xBCBCBC)
            end
            local suffix = ""
            if value.changesetting then
                local savething = value.changesetting
                if value.playersave then
                    savething = value.changesetting .. playerincontrol.idx
                end
                if savething ~= nil and globalsave[savething] ~= nil then
                    suffix = ": " .. booleantostring(globalsave[savething])
                end
            end
            local font = GoodFont
            if value.font then
                font = value.font
            end
            textplus.print{
                x = 265 + xoffset,
                y = 220+(spacing*key) + yoffset,
                --pivot = {0.5, 0.5},
                text = "<size 2>" .. value.name .. suffix .. "</size>",
                font = font,
                color = colortime*opacity,
                priority = 5
            }
        end

        -- [[ cursor rendering ]] --
        if xpostimer < xposgoto then
            xpostimer = xpostimer + 0.75
        else
            xpostimer = -xposgoto
        end


        cursorposX = 245 + xoffset + (math.abs(xpostimer) - xposgoto)
        cursorposY = 220 + (spacing*position)  + yoffset


        if fakecursorposY > cursorposY then
            fakecursorposY = math.max(cursorposY, fakecursorposY - 6)
        elseif fakecursorposY < cursorposY then
            fakecursorposY = math.min(cursorposY, fakecursorposY + 6)
        end

        if fakecursorposX > cursorposX then
            fakecursorposX = math.max(cursorposX, fakecursorposX - 20)
        elseif fakecursorposX < cursorposX then
            fakecursorposX = math.min(cursorposX, fakecursorposX + 20)
        end

        if playerincontrol == player2 then
            cursorGFX = Graphics.loadImage(Misc.resolveFile("GFX/player2pause.png"))
        else
            cursorGFX = Graphics.sprites.hardcoded["34-0"].img
        end
        Graphics.drawImageWP(cursorGFX, fakecursorposX, fakecursorposY, opacity, 5)


        -- [[ hard mode emblem ]] --
        if globalsave.HardMode then
            local Gamer = HardModeGFX
            if globalsave.HMLevelsBeat[Level.filename()] then
                Gamer = HardModeGFX2
            end
            Graphics.drawImageWP(Gamer, 550, 356, opacity, 5)
        end

        -- [[ low-res pichu easter egg ]] --
        if PichuTime then
            local lowrespichu
            if shinypichu then
                lowrespichu = Graphics.loadImage(Misc.resolveFile("shiny pichu.png"))
            else
                lowrespichu = Graphics.loadImage(Misc.resolveFile("npc-753.png"))
            end
            if pichutimer2 == 1 then
                if pichutimer < 46 then
                    pichutimer = pichutimer + 1
                else
                    pichutimer = 0
                end
                pichutimer2 = 0
            else
                pichutimer2 = 1
            end
            local sourceX = 0
            local sourceY = 0  + (pichutimer*52)
            Graphics.drawImageWP(lowrespichu, 375, 100, sourceX, sourceY, 51, 52, opacity, 5)
        end
    end
end

return newPauseMenu